#include <stdio.h>
#include <string.h>
#include "char_conv.h"
#include "misc.h"
#include "md5.h"

gchar *utf8(const gchar* utf8_str) {
  return g_locale_from_utf8(utf8_str, -1, NULL, NULL, NULL);
}
	
void gen_ip_str(char ip_str[16], uint32 ip_addr) {
	uint8 ip[4];
	if (ip_addr) {
		memcpy(ip, &ip_addr, 4);
		sprintf(ip_str, "%d.%d.%d.%d",ip[0], ip[1],ip[2], ip[3]);
	} else ip_str[0] = 0x00;
}

gchar * qq_encode_to_html
(uint8 *data, int len, const gchar *msg, const char *locale) {
	GString *encoded;
	
  uint8 font_attr, charset, font_name_len, bar;
	uint8 font_size, is_bold, is_italic, is_underline;
	uint8 font_name[256], color[3];
	gchar color_code[8];
	uint8 *cursor=data;
	gchar *ret;
						
  qq_read_packet_b(data, &cursor, len, &font_attr);
  qq_read_packet_data(data, &cursor, len, color, 3); // red,green,blue
  sprintf(color_code, "#%02x%02x%02x", color[0], color[1], color[2]);
	color_code[7] = 0x00;	
	
	qq_read_packet_b(data, &cursor, len, &bar);
  qq_read_packet_b(data, &cursor, len, &charset);
  qq_read_packet_b(data, &cursor, len, &bar);
  font_name_len = ((uint8 *)data + len - cursor);
  qq_read_packet_data(data, &cursor, len, font_name, font_name_len);
  font_name[font_name_len] = 0x00;

  font_size = font_attr & 0x1f; // last 5 bit
  is_bold = font_attr & 0x20;
  is_italic = font_attr & 0x40;
  is_underline = font_attr &0x80;
  gchar *font_name_locale = 
  	qq_to_locale(font_name, font_name_len, locale);
  
	encoded = g_string_sized_new(strlen(msg) + 128);
	// we ignore font name, size  here 
	// as windows' font name/size is different from *nix 
	// and cannot be used directly
	g_string_append_printf(encoded, 
		"<font color=\"%s\">", color_code);
	
	if(is_bold) g_string_append_printf(encoded, "<b>");
	if(is_italic) g_string_append_printf(encoded, "<i>");
	if(is_underline) g_string_append_printf(encoded, "<u>");

	g_string_append_printf(encoded, "%s", msg);
	
	if(is_underline) g_string_append_printf(encoded, "</u>");
	if(is_italic) g_string_append_printf(encoded, "</i>");
	if(is_bold) g_string_append_printf(encoded, "</b>");

	g_string_append_printf(encoded, "</font>");
  g_free(font_name_locale);

	ret = encoded->str;
	g_string_free(encoded, FALSE);
	
	return ret;
}

gchar * locale_to_qq
(const gchar *str, gssize len, const gchar *to_charset)  {
	gchar locale[64]; char ** from_charset = (char **)&locale;
	if (len < 0) len = -1;
	
	if (g_get_charset((G_CONST_RETURN char **)from_charset)) 
		strcpy(locale, "UTF-8"); locale[5] = 0x00;
	
	// compare to_locale and from_locale
	if ((! strcmp(locale, to_charset)) || // same locale
			(strstr(to_charset, "GB") && strstr(locale, "GB"))) // all GB locale
		return (gchar *)str; // no need to convert
	
	return g_convert(str, len, to_charset, locale, NULL, NULL, NULL);
}

gchar * qq_to_locale
(const gchar *str, gssize len, const gchar *from_charset)  {
	gchar locale[64]; char ** to_charset = (char **)&locale;
	
	if (len < 0) len = -1; // string is null terminated
	
	if (g_get_charset((G_CONST_RETURN char **)to_charset)) 
		strcpy(locale, "UTF-8"); locale[5] = 0x00;
	
	// compare to_locale and from_locale
	if ((! strcmp(locale, from_charset)) || // same locale
			(strstr(from_charset, "GB") && strstr(locale, "GB"))) // all GB locale
		return (gchar *)str; // no need to convert
	
	return g_convert(str, len, (const gchar *)locale, 
					from_charset, NULL, NULL, NULL);
}


void hex_dump
(unsigned char *buffer, int bytes) {
  int	i, j;
  int	ch;

  for (i = 0; i < bytes; i += 16) {
    printf("%04d: ", i);

    for (j = 0; j < 16; j ++)
      if ((i + j) < bytes) printf(" %02x", buffer[i + j]);
      else printf("   ");
    putchar(' ');
    putchar(' ');

    for (j = 0; j < 16 && (i + j) < bytes; j ++) {
      ch = buffer[i + j] & 127;
      if (ch < ' ' || ch == 127) putchar('.');
      else putchar(ch);
    }
    putchar('\n');
  }
}// hex_dump

void gen_pwkey
(unsigned char *pwd, unsigned char *pwkey) {
	md5_state_t ctx;
	md5_byte_t pwkey_tmp[16];
	
	md5_init(&ctx);
	md5_append(&ctx, pwd, strlen(pwd));
	md5_finish(&ctx, pwkey_tmp);
	// QQ2003 now uses double md5... stupid
	md5_init(&ctx);
	md5_append(&ctx, pwkey_tmp, 16);
	md5_finish(&ctx, pwkey);
}

void gen_session_md5
(unsigned char *md5_str, int uid, unsigned char session_key[16]) {
	unsigned char src[20];
	md5_state_t ctx;
	
	memcpy(src, &uid, 4);
	memcpy(src+4, session_key, 16);
	
	md5_init(&ctx);
	md5_append(&ctx, src, 20);
	md5_finish(&ctx, (md5_byte_t *)md5_str);
}
